import com.google.common.collect.Maps;
import com.myrest.provider.poi.work.entities.user.ESUser;
import com.myrest.provider.poi.work.entities.user.SysUser;
import com.mytest.provider.es.EsApplication;
import com.mytest.provider.es.clients.userFen;
import com.mytest.provider.es.config.EsConstant;
import com.mytest.provider.es.mapper.ElasticRepository;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.index.query.Operator;
import org.elasticsearch.index.query.QueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.aggregations.Aggregation;
import org.elasticsearch.search.aggregations.AggregationBuilder;
import org.elasticsearch.search.aggregations.AggregationBuilders;
import org.elasticsearch.search.aggregations.bucket.terms.StringTerms;
import org.elasticsearch.search.aggregations.metrics.avg.InternalAvg;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightField;
import org.elasticsearch.search.sort.SortBuilders;
import org.elasticsearch.search.sort.SortOrder;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.elasticsearch.core.ElasticsearchTemplate;
import org.springframework.data.elasticsearch.core.aggregation.AggregatedPage;
import org.springframework.data.elasticsearch.core.aggregation.impl.AggregatedPageImpl;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.test.context.junit4.SpringRunner;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * @Author: llq
 * @Date: 2020/4/10
 */
@RunWith(SpringRunner.class)
@SpringBootTest(classes= EsApplication.class)
public class searchindex {
    @Autowired
    private ElasticsearchTemplate template;

    @Autowired
    private com.mytest.provider.es.serviceImpl.indexservice indexservice;
    /*@Autowired
    private GoodsRepoistory goodsRepoistory;*/
    @Autowired
    ElasticRepository elasticRepository;
    @Autowired
    userFen userFen;


    @Test
    public void test01() {
        template.createIndex(ESUser.class);
        template.putMapping(ESUser.class);
    }

    @Test
    public void test02() {
        Map<String, Object> map = Maps.newHashMap();
        List<SysUser> sysUsers = userFen.selectUserAll(map);
        List<ESUser> esUsers = new ArrayList<>();
        sysUsers.forEach(sysUser -> {
            ESUser esUser = new ESUser();
            esUser.setId(sysUser.getId());
            esUser.setUsername(sysUser.getUsername());
            esUser.setPassword(sysUser.getPassword());
            esUser.setNickName(sysUser.getNickName());
            esUser.setSex(sysUser.getSex());
            esUsers.add(esUser);
        });
        elasticRepository.saveAll(esUsers);
    }

    @Test
    public void test03() {
        NativeSearchQueryBuilder queryBuilder = new NativeSearchQueryBuilder();
        queryBuilder.withQuery(QueryBuilders.matchQuery("xxx", "xxx").operator(Operator.OR));
        queryBuilder.withQuery(QueryBuilders.boolQuery()
                .must(QueryBuilders.matchQuery("xxx", "xxx").operator(Operator.AND))
                .filter(QueryBuilders.boolQuery().must(QueryBuilders.termQuery("xxx", "xxx"))));
        queryBuilder.withQuery(QueryBuilders.termQuery("xxx", "xxx"));
        Page<ESUser> search1 = elasticRepository.search(queryBuilder.build());


        queryBuilder.withPageable(PageRequest.of(1, 10));
        Page<ESUser> search2 = elasticRepository.search(queryBuilder.build());

        queryBuilder.addAggregation(AggregationBuilders.terms("ccc").field("xxx"));
        queryBuilder.addAggregation(AggregationBuilders.terms("ccc").field("xxx")
                .subAggregation(AggregationBuilders.avg("vvv").field("xxx")));
        AggregatedPage<ESUser> search = (AggregatedPage) elasticRepository.search(queryBuilder.build());
        StringTerms ccc = (StringTerms) search.getAggregation("ccc");
        List<StringTerms.Bucket> buckets = ccc.getBuckets();
        buckets.forEach(bucket -> {
//            InternalAvg ccc1 = (InternalAvg)bucket.getAggregations().asMap().get("ccc");
            long l = bucket.getKeyAsNumber().longValue();
            long docCount = bucket.getDocCount();
        });

       /* GET /xxx/_search
            {
                "query": {}
                "sort": [
                {
                    "price": {                            //根据price这个字段来排序
                    "order": "desc"
                }
                }
        }*/
        queryBuilder.withSort(SortBuilders.fieldSort("xxx").order(SortOrder.DESC));
        Page<ESUser> search3 = elasticRepository.search(queryBuilder.build());


        /*GET /xxx/_search
        {
            "query":{}
            "highlight": {
            "pre_tags": ["<tag1>"],         //设置高亮标签
            "post_tags": ["</tag2>"],      //设置高亮标签
            "fields": {
                "title": {}          //使title字段高亮显示
                "content": {
                    "type"："plain"    //使用那种高亮显示
                }
            }
        }
        }*/
        String preTag = "<font color='#dd4b39'>";//google的色值
        String postTag = "</font>";
        queryBuilder.withHighlightFields(
                new HighlightBuilder.Field("ideaTitle").preTags(preTag).postTags(postTag),
                new HighlightBuilder.Field("ideaContent").preTags(preTag).postTags(postTag));
        new HighlightBuilder.Field("xxx").preTags(EsConstant.HIGH_LIGHT_START_TAG)
                .postTags(EsConstant.HIGH_LIGHT_END_TAG);

        // 多索引查询
        queryBuilder.withIndices(EsConstant.INDEX_NAME.TRAVEL);

        // 组合查询，boost即为权重，数值越大，权重越大
        QueryBuilder q = QueryBuilders.boolQuery()
                .should(QueryBuilders.multiMatchQuery("xxx", "title").boost(3))
                .should(QueryBuilders.multiMatchQuery("xxx", "passCity", "description").boost(2))
                .should(QueryBuilders.multiMatchQuery("xxx", "content", "keyword").boost(1));
        queryBuilder.withQuery(q);

//        浏览器-请求-nginx-zuul-eureka-tomcat-servletcontext-servlet实例化-servlet初始化init()-service()servletrequest-servletresponse-distory()
    }

   /* @Test
    public void c(){
        ArrayList<String> strings = new ArrayList<>();
        ArrayList<String> invocationHandler = (ArrayList<String>)Proxy.getInvocationHandler(
                strings.getClass().getClassLoader(),
                strings.getClass().getInterfaces(),
                new InvocationHandler() {
                    @Override
                    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                        return method.invoke(strings, args);
                    }
                });
        invocationHandler.add("ss");
        System.out.println(strings);
    }*/

    private static final ExecutorService es = Executors.newFixedThreadPool(10);

    public static void execute(Runnable runnable) {
        es.submit(runnable);
    }

    public static int recursionBinarySearch(int[] arr, int key, int low, int high) {
        if (key < arr[low] || key > arr[high] || low > high) {
            return -1;
        }
        int middle = (low + high) / 2;            //初始中间位置
        if (arr[middle] > key) {
            //比关键字大则关键字在左区域
            return recursionBinarySearch(arr, key, low, middle - 1);
        } else if (arr[middle] < key) {
            //比关键字小则关键字在右区域
            return recursionBinarySearch(arr, key, middle + 1, high);
        } else {
            return middle;
        }
    }


   /* public static void main(String[] args){
        int[] arr = {6,3,2,1,7};
        for(int i = 0;i<arr.length-1;i++){//外层循环n-1
            for(int j = 0;j<arr.length-i-1;j++){//内层循环n-i-1
                if(arr[j]>arr[j+1]){//从第一个开始，往后两两比较大小，如果前面的比后面的大，交换位置
                    int tmp = arr[j];
                    arr[j] = arr[j+1];
                    arr[j+1] = tmp;
                }
            }
        }
        System.out.println(Arrays.toString(arr));
    }*/

    // 63721     循环4次
    // 36217  第一次 最大的到最后           4
    // 32167  第二次 第二大的到最后第二位    3
    // 21367  第三次 第三大的到最后第三位    2
    // 12367  第四次 第四大的到最后第四位    1


   /* @Test
    public <T> AggregatedPage<T> mapResults(SearchResponse response, Class<T> clazz, Pageable pageable) {

        // 获取高亮搜索数据
        List<Travel> list = new ArrayList<Travel>();
        SearchHits hits = response.getHits();
        for (SearchHit searchHit : hits) {
            if (hits.getHits().length <= 0) {
                return null;
            }
            Travel data = new Travel();
            // 公共字段
            data.setId(new Double(searchHit.getId()).longValue());
            data.setType(String.valueOf(searchHit.getSourceAsMap().get("type")));
            data.setStatus(String.valueOf(searchHit.getSourceAsMap().get("status")));
            data.setTitle(String.valueOf(searchHit.getSourceAsMap().get("title")));
            data.setContent(String.valueOf(searchHit.getSourceAsMap().get("content")));
            data.setIgnoreContent(String.valueOf(searchHit.getSourceAsMap().get("ignoreContent")));
            data.setDescription(String.valueOf(searchHit.getSourceAsMap().get("description")));
            Object createTime = searchHit.getSourceAsMap().get("createTime");
            Object updateTime = searchHit.getSourceAsMap().get("updateTime");
            if (createTime != null) {
                data.setCreateTime(new Date(Long.valueOf(createTime.toString())));
            }
            if (updateTime != null) {
                data.setUpdateTime(new Date(Long.valueOf(updateTime.toString())));
            }

            // 个性字段
            data.setKeyword(String.valueOf(searchHit.getSourceAsMap().get("keyword")));
            data.setPassCity(String.valueOf(searchHit.getSourceAsMap().get("passCity")));

            // 反射调用set方法将高亮内容设置进去
            try {
                for (String field : highlightFields) {
                    HighlightField highlightField = searchHit.getHighlightFields().get(field);
                    if (highlightField != null) {
                        String setMethodName = parSetName(field);
                        Class<? extends Travel> poemClazz = data.getClass();
                        Method setMethod = poemClazz.getMethod(setMethodName, String.class);

                        String highlightStr = highlightField.fragments()[0].toString();
                        // 截取字符串
                        if ("content".equals(field) && highlightStr.length() > 50) {
                            highlightStr = StringUtil.truncated(highlightStr,
                                    EsConstant.HIGH_LIGHT_START_TAG, EsConstant.HIGH_LIGHT_END_TAG);
                        }

                        setMethod.invoke(data, highlightStr);
                    }
                }

            } catch (Exception e) {
                e.printStackTrace();
            }
            list.add(data);
        }
        if (list.size() > 0) {
            AggregatedPage<T> result = new AggregatedPageImpl<T>((List<T>) list, pageable,
                    response.getHits().getTotalHits());

            return result;
        }
        return null;
    }
*/




}


